#ifndef DATABASEQUEUE_H
#define DATABASEQUEUE_H

#include <QObject>
#include <QThread>
#include <QSqlDatabase>
#include <functional>
#include <QEventLoop>
#include <QQueue>
#include <QSemaphore>
#include <QMutex>
#include <QMutexLocker>
#include <QSqlQuery>
#include <QSqlError>

typedef struct SqlQueue{
    QString sql{""};
    std::function<void (const  QSqlQuery &query)> callback{[&](const  QSqlQuery &query){}};
    bool isValid{false};
}SqlQueue;

class DatabaseQueue : public QObject
{
    Q_OBJECT
public:
    static DatabaseQueue *instance();

    QSqlQuery execSql(const QString &sql);

    void execAsyncSql(const QString &sql);

    void execSql(const SqlQueue &queue);

    void stop();

signals:
    void createDatabaseConnection();

public slots:
    void createDatabaseConnectionSlot();

private:
    explicit DatabaseQueue(QObject *parent = nullptr);
    void connectDatabase();
    void dealQueue();
    void reportSqlError(QSqlQuery &query);

private:
    static DatabaseQueue            *m_instance;
    QThread                         *m_thread;
    QMutex                          m_dbMutex;
    QSqlDatabase                    m_database;
    QQueue<SqlQueue>                m_highPriorityQueue;
    QMutex                          m_highPQMutex;
    QQueue<SqlQueue>                m_lowPriorityQueue;
    QMutex                          m_lowPQMutex;
    bool                            m_running{false};
    QSemaphore                      m_semaphore;
};

#endif // DATABASEQUEUE_H
